package cn.dakaqi.services.impl;

import cn.dakaqi.dao.GroupDao;
import cn.dakaqi.dao.GroupVolunteerDao;
import cn.dakaqi.entities.Group;
import cn.dakaqi.entities.GroupVolunteer;
import cn.dakaqi.entities.Task;
import cn.dakaqi.entities.user.Volunteer;
import cn.dakaqi.qnzyz.BHMember;
import cn.dakaqi.qnzyz.BHMemberService;
import cn.dakaqi.qnzyz.BHOrgService;
import cn.dakaqi.services.GroupMonthDataService;
import cn.dakaqi.services.GroupService;
import cn.dakaqi.services.PlatformGroup2Service;
import cn.dakaqi.services.user.VolunteerService;
import cn.dakaqi.utils.*;
import cn.dakaqi.utils.exception.ServiceRuntimeException;
import cn.dakaqi.utils.rongYun.PushGroupMesssage;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springside.modules.persistence.DynamicSpecifications;
import org.springside.modules.persistence.SearchFilter;
import org.springside.modules.utils.Clock;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by chunyang on 2016/4/13.
 */
@Component(value = "groupService")
@Transactional
public class GroupServiceImpl implements GroupService
{
    @Autowired
    private GroupDao groupDao;
    @Autowired
    private VolunteerService volunteerService;
    @Autowired
    private GroupVolunteerDao groupVolunteerDao;
    @Autowired
    PlatformGroup2Service platformGroupService;
    @Autowired
    GroupMonthDataService groupMonthDataService;
    @Autowired
    BHOrgService bhOrgService;
    @Autowired
    BHMemberService bhMemberService;

    @Autowired
    BaseDAO baseDAO;

    public Group queryById(Long id)
    {
        return this.groupDao.findOne(id);
    }

    @Override
    public void save(String param,String client) throws ServiceRuntimeException
    {
        JSONObject jsonObject = JSON.parseObject(param);
        String memberCode = jsonObject.getString("memberCode");
        String name = jsonObject.getString("name");
        String logo = jsonObject.getString("logo");
        String demo = jsonObject.getString("demo");//简介
        String serviceField = jsonObject.getString("serviceField");//服务领域
        String setupDate = jsonObject.getString("setupDate");//成立日期
        String regAddress = jsonObject.getString("regAddress");//注册地
        String prvoince = jsonObject.getString("prvoince");//注册地
        String city = jsonObject.getString("city");//注册地
        String district = jsonObject.getString("district");//注册地
        String monitor = jsonObject.getString("monitor");//负责人
        String phone = jsonObject.getString("phone");
        Group group = new Group();
        Volunteer volunteer = volunteerService.findByMemberCode(memberCode);

        group.setClient(client);
        group.setName(name);
        group.setLogo(logo);
        group.setDemo(demo);
        group.setServiceField(serviceField);
        group.setSetupDate(setupDate);
        group.setRegAddress(regAddress);
        group.setMonitor(monitor);
        group.setPhone(phone);
        group.setCreateUser(volunteer);
        group.setProvince(prvoince);
        group.setCity(city);
        group.setDistrict(district);
        this.save(group);

    }

    @Override
    public Group save(Group group) throws ServiceRuntimeException
    {
        //检查当前城市是否以有相同名称的社团
        Map<String, SearchFilter> filters = Maps.newHashMap();
        filters.put("name", new SearchFilter("name", SearchFilter.Operator.EQ, group.getName()));
        Specification<Group> spec = DynamicSpecifications.bySearchFilter(filters.values(), Group.class);

        List<Group> groups = this.groupDao.findAll(spec);
        if(null != groups && groups.size()>0)
            throw new ServiceRuntimeException("本市内已有相同名称的社团了");

        //提交数据至北航
//        private String groupCode;//志愿者团体一号通编号,全网唯一不能修改
//        private String orgCode;//团组织一号通编号,全网唯一
//        private String orgName;//所属团组织名称
//        private String groupName;//志愿者团体名称
//        private String groupType;//志愿者团体类型 (1 非独立法人 2 为独立法人) 如果是2,志愿者团体机构代码必须给出
//        private String groupAdmCode;//志愿者团体机构代码 ，如果groupType为2是必须的，groupType为1不需要填写 参考例子：01271075-5
//        private String groupAddress;//志愿者团体地址
//        private String groupProvince;//省份
//        private String groupCity;//城市
//        private String groupDistrict;//区县
//        private String groupPostcode;//邮政编码
//        private String groupAdmMobile;//志愿者团体管理员手机号码，用做登陆
//        private String groupAdmPwd;//志愿者团体管理员密码 MD5后的
//        private String groupAdmName;//志愿者团体管理员姓名
//        private String groupAdmIdNo;//志愿者团体管理员身份证
//        private String groupAdmTel;//志愿者团体管理员工作联系电话 (区号-号码)
        Map<String, String> map = new HashMap<String, String>();
        map.put("groupName", group.getName());
        map.put("groupAdmCode", group.getCode());
        map.put("groupProvince", group.getProvince());
        map.put("groupCity", group.getCity());
        map.put("groupDistrict", group.getDistrict());
        map.put("groupAddress", group.getRegAddress());
        map.put("groupPostcode", "");
//
//        map.put("groupAdmMobile", group.getCreateUser().getMobile());
//        String sql = "select PASSWORD from U_USER where ID = " + group.getCreateUser().getUserId();
//        List<Map<String,String>> list = baseDAO.queryNativeSql(sql);
//        if(null != list && list.size()>0)
//            map.put("groupAdmPwd",list.get(0).get("PASSWORD"));
//        else
//            map.put("groupAdmPwd", MD5Util.MD5("123456"));
//
//        map.put("groupAdmName",group.getCreateUser().getRealName());
//        map.put("groupAdmIdNo",group.getCreateUser().getCardNO());
//

        map.put("groupAdmMobile", "");
        map.put("groupAdmPwd", "");
        map.put("groupAdmName", group.getMonitor());
        map.put("groupAdmIdNo", "");
        map.put("groupAdmTel", group.getCreateUser().getMobile());
        map.put("groupCategory", "");
        map.put("groupSummary", group.getDemo());
        try
        {
            String groupCode = bhOrgService.reg4Social(map);
            if(StringUtils.isNotBlank(groupCode))
                group.setGroupCode(groupCode);
            else
                throw new ServiceRuntimeException("中央团体注册失败");
        }
        catch (Exception e)
        {
            e.printStackTrace();
            try
            {
                throw e;
            } catch (Exception e1)
            {
                e1.printStackTrace();
            }
        }
//
//        if(StringUtils.isNotBlank(group.getPrvoince()))
//            group.setGroupCode(createGroupCode(group.getPrvoince(), "", ""));
//        else
//            group.setGroupCode(createGroupCode("江苏省", "", ""));
//
//
        group.setCreateTime(Clock.DEFAULT.getCurrentDate());
        group.setTimes(0L);
        group.setVolunteers(1);
        group.setMonitor(group.getCreateUser().getRealName());
        group.setPhone(group.getCreateUser().getMobile());

        this.groupDao.save(group);
        //创建群组
        List<String > userIds = new ArrayList<String>();
        userIds.add(group.getCreateUser().getMemberCode());
        PushGroupMesssage.getInstance().createGroup(PushGroupMesssage.GROUP_TYPE_GROUP,userIds,group.getGroupCode(),group.getShortName());

        try
        {

            Volunteer volunteer = group.getCreateUser();
            String voluteerCode = volunteer.getVolunteerCode();
            if(StringUtils.isBlank(voluteerCode) || "null".equals(voluteerCode.toLowerCase()))
            {
                voluteerCode = bhMemberService.simpleReg(BHMember.toBHMember(volunteer, group.getGroupCode()));
                volunteer.setVolunteerCode(voluteerCode);
                this.volunteerService.updateVolunteer(volunteer);

            }

            if(StringUtils.isNotBlank(voluteerCode))
            {
                //社团创建者自动加入当前社团，并为管理员
                GroupVolunteer groupVolunteer = new GroupVolunteer();
                groupVolunteer.setCreateTime(Clock.DEFAULT.getCurrentDate());
                groupVolunteer.setGroup(group);
                groupVolunteer.setVolunteer(group.getCreateUser());
                groupVolunteer.setStatus(DKQConstant.APPLY_STATUS_OK);
                groupVolunteer.setRole(DKQConstant.ROLES_CREATEER);
                this.groupVolunteerDao.save(groupVolunteer);


                try
                {
                    //通知北航加入新创建的组织
                    bhMemberService.joinGroup(voluteerCode, group.getGroupCode());
                    //添加北航社团管理员,北航会抛出异常，则在北航系统中相应的社团是没有管理员的

                    String password = "";
                    String sql = "select PASSWORD from U_USER where ID = " + group.getCreateUser().getUserId();
                    List<Map<String,String>> list = baseDAO.queryNativeSql(sql);
                    if(null != list && list.size()>0)
                        password = list.get(0).get("PASSWORD");
                    else
                        password =  MD5Util.MD5("123456");

                    bhOrgService.addManager(group.getGroupCode(), group.getCreateUser().getRealName(), group.getCreateUser().getMobile(), password, group.getName(), group.getCreateUser().getCardNO(), group.getPhone());

                } catch (Exception e)
                {
                    e.printStackTrace();
                }
            }
        } catch (Exception e)
        {
            e.printStackTrace();
        }

        //当前社团月统计数据，默认前六个月数据
        groupMonthDataService.createDefaultData(group.getGroupCode());

        return group;
    }
    @Override
    public Group update(Group group) throws ServiceRuntimeException
    {
        return this.groupDao.save(group);
        //当前社团月统计数据，默认前六个月数据
        //groupMonthDataService.createDefaultData(group.getGroupCode());
    }

    @Override
    public void delGroup(String groupCode) throws ServiceRuntimeException
    {
        Group group = this.findByGroupCode(groupCode);
        if(null != group)
        {
            group.setDelStatus(DKQConstant.DEL_YES);
            this.update(group);
        }
    }

    @Override
    public void delGroup(Long id) throws ServiceRuntimeException
    {
        Group group = this.groupDao.findOne(id);
        if(null != group)
        {
            group.setDelStatus(DKQConstant.DEL_YES);
            this.update(group);
        }
    }

    @Override
    public Group findByGroupCode(String groupCode) throws ServiceRuntimeException
    {
        Map<String, SearchFilter> filters = Maps.newHashMap();
        filters.put("groupCode", new SearchFilter("groupCode", SearchFilter.Operator.EQ, groupCode));
        Specification<Group> spec = DynamicSpecifications.bySearchFilter(filters.values(), Group.class);

        List<Group> list = this.groupDao.findAll(spec);
        if(null == list || list.size() ==0)
            return null;
        else
            return list.get(0);
    }

    @Override
    public Group findOne(Long id) throws ServiceRuntimeException
    {
        return this.groupDao.findOne(id);
    }

    public Page<Group> queryByName(String name)
    {
        PageRequest pageRequest = buildPageRequest(1, 20, "");

        Map<String, SearchFilter> filters = Maps.newHashMap();
        filters.put("name", new SearchFilter("name", SearchFilter.Operator.LIKE, name));
        Specification<Group> spec = DynamicSpecifications.bySearchFilter(filters.values(), Group.class);

        return this.groupDao.findAll(spec, pageRequest);
    }

    @Override
    public Page<Group> searchByName(String name, int pageNumber) throws ServiceRuntimeException
    {
        Sort sort = new Sort(Sort.Direction.DESC, "createTime");
        PageRequest pageRequest = new PageRequest(pageNumber - 1, 20, sort);

        Map<String,Object> map = new HashMap<String, Object>();
        //map.put("LIKE_NAME",name);
        //Map<String, SearchFilter> filters = SearchFilter.parse(map);

        Map<String, SearchFilter> filters = Maps.newHashMap();
        filters.put("name", new SearchFilter("name", SearchFilter.Operator.LIKE, name));
        Specification<Group> spec = DynamicSpecifications.bySearchFilter(filters.values(), Group.class);
        return this.groupDao.findAll(spec, pageRequest);
    }

    @Override
    public void dissolve(String param)
    {
        JSONObject jsonObject = JSON.parseObject(param);
        String memberCode = jsonObject.getString("memberCode");
        String groupCode = jsonObject.getString("groupCode");
        this.delGroup(groupCode);
    }

    @Override
    public void joinOrg(String param) throws ServiceRuntimeException
    {
        JSONObject jsonObject = JSON.parseObject(param);
        String groupCode = jsonObject.getString("groupCode");
        String parentCode = jsonObject.getString("parentCode");
        String memberCode  = jsonObject.getString("memberCode");
        long platform  = jsonObject.getLongValue("platform");
        if(StringUtils.isBlank(groupCode))
            throw new ServiceRuntimeException("当前社团无效");
        if(StringUtils.isBlank(parentCode))
            throw new ServiceRuntimeException("上一级编码无效");
        if(StringUtils.isBlank(memberCode))
            throw new ServiceRuntimeException("当前用户无效");
        if(platform ==0L)
            throw new ServiceRuntimeException("平台无效");
        //int status = jsonObject.getIntValue("status");
        joinOrg(groupCode, platform, parentCode, memberCode, DKQConstant.APPLY_STATUS);
    }

    @Override
    public void joinOrg(String groupCode,long platform,String parentCode, String memberCode,int status) throws ServiceRuntimeException
    {
        Group group = findByGroupCode(groupCode);
        if(null != group)
        {
            Map<String, SearchFilter> filters = Maps.newHashMap();
            filters.put("group.groupCode", new SearchFilter("group.groupCode", SearchFilter.Operator.EQ, groupCode));
            filters.put("status", new SearchFilter("status", SearchFilter.Operator.EQ, DKQConstant.APPLY_STATUS_OK));
            filters.put("delStatus", new SearchFilter("delStatus", SearchFilter.Operator.EQ, DKQConstant.DEL_NO));
            Specification<GroupVolunteer> spec = DynamicSpecifications.bySearchFilter(filters.values(), GroupVolunteer.class);
            List<GroupVolunteer> list = this.groupVolunteerDao.findAll(spec);
            if(null != list && list.size()>0)
            {
                List<Volunteer> volunteers = new ArrayList<Volunteer>();
                for(GroupVolunteer gv:list)
                    volunteers.add(gv.getVolunteer());

                if(volunteers.size()>0)
                    this.platformGroupService.save(group.getId(),platform,parentCode,status,volunteers);
            }

        }
    }

    @Override
    public List<Group> findNameLike(String name,int size)
    {
        Sort sort = new Sort(Sort.Direction.DESC, "createTime");
        if(size ==0)
            size = 1000;
        PageRequest pageRequest = new PageRequest(0, size, sort);
        Map<String, SearchFilter> filters = Maps.newHashMap();
        filters.put("delStatus", new SearchFilter("delStatus", SearchFilter.Operator.EQ, DKQConstant.DEL_NO));
        filters.put("name", new SearchFilter("name", SearchFilter.Operator.LIKE, name.trim()));
        Specification<Group> spec = DynamicSpecifications.bySearchFilter(filters.values(), Group.class);
        Page<Group> data =  this.groupDao.findAll(spec, pageRequest);
        if(null == data || data.getContent() == null || data.getContent().size() ==0)
            return null;
        return data.getContent();
    }

    @Override
    public Group findByGroupName(String name)
    {
        Map<String, SearchFilter> filters = Maps.newHashMap();
        filters.put("delStatus", new SearchFilter("delStatus", SearchFilter.Operator.EQ, DKQConstant.DEL_NO));
        filters.put("name", new SearchFilter("name", SearchFilter.Operator.EQ, name.trim()));
        Specification<Group> spec = DynamicSpecifications.bySearchFilter(filters.values(), Group.class);
        List<Group> data =  this.groupDao.findAll(spec);

        if(null == data || data.size() ==0)
            return null;
        else
            return data.get(0);
    }

    @Override
    public List<Group> findByCity(String city,int size) throws ServiceRuntimeException
    {
        Sort sort = new Sort(Sort.Direction.DESC, "createTime");
        if(size ==0)
            size = 1000;
        PageRequest pageRequest = new PageRequest(0, size, sort);
        Map<String, SearchFilter> filters = Maps.newHashMap();
        filters.put("delStatus", new SearchFilter("delStatus", SearchFilter.Operator.EQ, DKQConstant.DEL_NO));
        filters.put("city", new SearchFilter("city", SearchFilter.Operator.LIKE, city.trim()));
        Specification<Group> spec = DynamicSpecifications.bySearchFilter(filters.values(), Group.class);
        Page<Group> data =  this.groupDao.findAll(spec, pageRequest);
        if(null == data || data.getContent() == null || data.getContent().size() ==0)
            return null;
        return data.getContent();
    }

    @Override
    public List<Group> findHot(int size) throws ServiceRuntimeException
    {
        Sort sort = new Sort(Sort.Direction.DESC, "actvitys");
        if(size ==0)
            size = 1000;
        PageRequest pageRequest = new PageRequest(0, size, sort);
        Map<String, SearchFilter> filters = Maps.newHashMap();
        filters.put("delStatus", new SearchFilter("delStatus", SearchFilter.Operator.EQ, DKQConstant.DEL_NO));
        Specification<Group> spec = DynamicSpecifications.bySearchFilter(filters.values(), Group.class);
        Page<Group> data =  this.groupDao.findAll(spec, pageRequest);
        if(null == data || data.getContent() == null || data.getContent().size() ==0)
            return null;
        return data.getContent();
    }

    @Override
    public List<Group> findServiceFieldLike(String content,int size)
    {
        Sort sort = new Sort(Sort.Direction.DESC, "createTime");
        if(size ==0)
            size = 1000;
        PageRequest pageRequest = new PageRequest(0, size, sort);
        Map<String, SearchFilter> filters = Maps.newHashMap();
        filters.put("delStatus", new SearchFilter("delStatus", SearchFilter.Operator.EQ, DKQConstant.DEL_NO));
        filters.put("serviceField", new SearchFilter("serviceField", SearchFilter.Operator.LIKE, content.trim()));
        Specification<Group> spec = DynamicSpecifications.bySearchFilter(filters.values(), Group.class);
        Page<Group> data =  this.groupDao.findAll(spec, pageRequest);
        if(null == data || data.getContent() == null || data.getContent().size() ==0)
            return null;
        return data.getContent();
    }

    /**
     * 创建分页请求.
     */
    private PageRequest buildPageRequest(int pageNumber, int pagzSize, String sortType) {
        Sort sort = null;
        if ("auto".equals(sortType)) {
            sort = new Sort(Sort.Direction.DESC, "id");
        } else if ("title".equals(sortType)) {
            sort = new Sort(Sort.Direction.ASC, "title");
        }else if (StringUtils.isBlank(sortType)) {
            sort = new Sort(Sort.Direction.DESC, "id");
        }

        return new PageRequest(pageNumber - 1, pagzSize, sort);
    }

    /**
     * 创建动态查询条件组合.
     */
    private Specification<Task> buildSpecification(Long userId, Map<String, Object> searchParams) {
        Map<String, SearchFilter> filters = SearchFilter.parse(searchParams);
        filters.put("user.id", new SearchFilter("user.id", SearchFilter.Operator.EQ, userId));
        Specification<Task> spec = DynamicSpecifications.bySearchFilter(filters.values(), Task.class);
        return spec;
    }

    //志愿者一号通：所在团体的省编号（2位）+所在省人数排序编号（8位，剩下的补0）+随机数（1位）

    //志愿团体一号通：所在团组织机构代码（后9位）+排序号（3位）

    //活动一号通：1.体制内团体的活动—发布活动的团体所在团组织的省份（2位）+创建时间年份（4位）+排序号（7位）2.社会团体—发布活动的团体所在的省份（2位）+创建时间年份（4位）+排序号（7位）


    private String createGroupCode(String province,String city,String district)
    {
        StringBuffer sb = new StringBuffer();
        String code = groupDao.queryProvinceCode(province);
        sb.append("G");
        sb.append(code);
        sb.append(DateUtil.currentDateStringTrim());
        String targetStr[] = Identities.uuid().split("-");
        sb.append(targetStr[1].toUpperCase());
        return sb.toString();
    }

}
